<template>
  <div class="bigBox" v-loading="timelineLoad">
    <canvas id="timeline" :width="width" :height="height" style="cursor: pointer; border: 1px solid #ebeef5; background-color: #fafafa" ondragstart="return false;"></canvas>
  </div>
</template>
<script>
var canvasColors = ['rgba(249,97,89,0.8)', 'rgba(55,202,65,0.8)']
// var scaleLineCorols = '#E6E6E6' // 刻度线颜色
var scaleLineCorols = '#7785A3' // 刻度线颜色
var fontColor = '#5C5C5C' // 字体颜色
var axisColor = '#1989FA' // 中轴线
var rulesContent = '#e6e6e6' // 卡尺上面颜色
var moveLineColor = '#000000'
var scaleH = 35
var moveLineH = 60
var moveTextH = 75
var minutes_per_step = [1, 2, 5, 10, 15, 20, 30, 60, 120, 180, 240, 360, 720, 1440] // min/格
var graduation_step = 20 // 刻度间最小宽度，单位px
var hours_per_ruler = 24 // 时间轴显示24小时
var distance_between_gtitle = 80
var zoom = 24
var g_mousedownCursor = null // 拖动mousedown的位置
var font = '12px pf'
export default {
  props: ['timeList'],
  data() {
    return {
      width: 1040,
      // width: 1900,
      height: 90,
      canvas: null,
      ctx: null,
      canvansW: 0,
      canVansH: 0,
      start_timestamp: null, //  渲染刻度开始时间
      g_isMousedown: false, // 拖动mousedown标记
      g_isMousemove: false, // 拖动mousemove标记
      returnTime: null, // mouseup返回时间
      // /*模拟数据*/
      num: new Date('2020-07-02 12:40:30').getTime() - new Date('2020-07-02 10:10:50').getTime(),
      timecell: [
        // {
        //   beginTime: new Date('2020-07-02 10:10:50').getTime() + (new Date('2020-07-02 12:40:30').getTime() - new Date('2020-07-02 10:10:50').getTime()),
        //   endTime: new Date('2020-07-02 12:40:30').getTime() + (new Date('2020-07-02 12:40:30').getTime() - new Date('2020-07-02 10:10:50').getTime()),
        //   style: {
        //     background: canvasColors[1],
        //   },
        // },
      ],
      timecellList: {},
      flag: false,
      timelineLoad: false,
    }
  },
  watch: {
    timeList: {
      deep: true,
      handler(newVal, oldVal) {
        // this.canvas = null
        // this.ctx = null
        // this.canvansW = 0
        // this.canVansH = 0
        this.initTImeList(newVal, this.flag)
      },
    },
  },
  created() {
    this.initTImeList(this.timeList, this.flag)
  },
  mounted() {
    this.againRend()
    this.flag = true
    this.timelineLoad = false
  },
  updated() {
    if (this.flag) {
      g_mousedownCursor = null
      hours_per_ruler = 24 // 时间轴显示24小时(重置原始放大倍数)
      this.againRend()
      this.timelineLoad = false
    }
  },
  methods: {
    initTImeList(timecellList, flag) {
      this.start_timestamp = new Date(`${timecellList.datesign} 00:00:00`).getTime() //  渲染刻度开始时间
      if (!timecellList.jsonstr) {
        this.timecell = []
        this.againRend()
        return
      }
      if (timecellList.datesign === '') {
        this.timecell = []
        this.againRend()
        return
      }
      this.timelineLoad = true
      const list = JSON.parse(timecellList.jsonstr)
      const arr = []
      let start = ''
      let end = ''
      let lastEnd = ''
      // let lastStart = ''
      // console.log('删除前:', list)
      // 判断数组是否满足b1和b2条件
      list.forEach((item, index) => {
        if (index > 0) {
          const b1 = list[index].startTime < list[index - 1].endTime // 判断当前开始时间<上一条的结束时间
          const b2 = list[index].startTime === list[index - 1].startTime && list[index].endTime > list[index - 1].endTime // 判断本次的开始时间=上一次的开始时间 但是本次的结束时间>上次的结束时间
          if (b2) {
            // 删除上一项
            // console.log('本次的开始时间=上一次的开始时间 但是本次的结束时间>上次的结束时间', item)
            list.splice(index - 1, 1)
          } else if (b1) {
            // 本次的结束时间>上次的结束时间
            // console.log(list[index].startTime, '-----当前开始时间<上一次结束时间-----', list[index - 1].endTime)
            // 删除当前项
            list.splice(index, 1)
          }
        }
      })
      // console.log('删除后:', list)
      list.forEach((item, index) => {
        // 存储第一次时间
        if (index === 0) {
          start = item.startTime
          // 判断第一个时间是否大于00点
          if (new Date(start).getTime() > this.start_timestamp) {
            arr.push({
              beginTime: new Date(this.start_timestamp).getTime() + (new Date(item.startTime).getTime() - new Date(this.start_timestamp).getTime()),
              endTime: new Date(item.startTime).getTime() + (new Date(item.startTime).getTime() - new Date(this.start_timestamp).getTime()),
              style: {
                background: canvasColors[0],
              },
            })
          }
          // console.log('first:', arr)
        }
        if (index === list.length - 1) {
          lastEnd = item.endTime
        }
        if (index < list.length - 1) {
          if (list[index].endTime !== list[index + 1].startTime) {
            end = item.endTime
            // 绿色段
            arr.push({
              beginTime: new Date(start).getTime() + (new Date(end).getTime() - new Date(start).getTime()),
              endTime: new Date(end).getTime() + (new Date(end).getTime() - new Date(start).getTime()),
              style: {
                background: canvasColors[1],
              },
            })
            // 红色段
            arr.push({
              // 将上一次的结束日期作为开始日期、当前下标的开始日期作为结束日期，渲染丢失段
              beginTime: new Date(end).getTime() + (new Date(list[index + 1].startTime).getTime() - new Date(end).getTime()),
              endTime: new Date(list[index + 1].startTime).getTime() + (new Date(list[index + 1].startTime).getTime() - new Date(end).getTime()),
              style: {
                background: canvasColors[0],
              },
            })
            // lastStart = list[index].endTime // 做为红色段最后一次的开始时间
            start = list[index + 1].startTime // 下一次的开始时间
          }
        } else {
          var lastTime = new Date(item.endTime).getTime()
          // 检测结果-判断最后一段是否小于24点
          if (this.timeList.xjType === 0) {
            // 获取明天时间
            var day3 = new Date(timecellList.datesign)
            day3.setTime(day3.getTime() + 24 * 60 * 60 * 1000)
            var s3 = day3.getFullYear() + '-' + (day3.getMonth() + 1) + '-' + day3.getDate()
            var tomorrow = new Date(`${s3} 00:00:00`).getTime()
            this.lastLeg(arr, lastTime, tomorrow)
          } else {
            // 手动巡检-判断最后一点是不是等于当前时间
            const currentTime = new Date(this.timeList.endtime).getTime()
            this.lastLeg(arr, lastTime, currentTime)
          }
        }
      })
      // 最后一段红色段
      // arr.push({
      //   beginTime: new Date(lastStart).getTime() + (new Date(start).getTime() - new Date(start).getTime()),
      //   endTime: new Date(start).getTime() + (new Date(start).getTime() - new Date(start).getTime()),
      //   style: {
      //     background: canvasColors[0],
      //   },
      // })
      // 最后一段绿色段
      arr.push({
        beginTime: new Date(start).getTime() + (new Date(lastEnd).getTime() - new Date(start).getTime()),
        endTime: new Date(lastEnd).getTime() + (new Date(lastEnd).getTime() - new Date(start).getTime()),
        style: {
          background: canvasColors[1],
        },
      })
      this.timecell = arr
      // console.log(this.timecell)
    },
    // 重新渲染-先清除画布在渲染
    againRend() {
      // mounted 周期中不调用清除画布
      if (this.flag) {
        this.clearCanvas()
      }
      this.canvas = document.getElementById('timeline')
      this.ctx = this.canvas.getContext('2d')
      this.canvansW = this.canvas.width
      this.canVansH = this.canvas.height
      this.init(this.start_timestamp, this.timecell)
    },
    lastLeg(arr, lastTime, timer) {
      if (lastTime < timer) {
        arr.push({
          beginTime: lastTime + (timer - lastTime),
          endTime: timer + (timer - lastTime),
          style: {
            background: canvasColors[0],
          },
        })
      }
    },
    /**
     * 初始化
     * @param {*} start_timestamp 最左侧时间
     * @param {*} timecell 录像段数组
     */
    init(start_timestamp, timecell) {
      this.drawCellBg()
      this.add_graduations(start_timestamp) // 初始时间轴 刻度
      this.add_cells(timecell)
      this.drawLine(0, this.canVansH, this.canvansW, this.canVansH, 'transparent', 1) // 时间轴border-bottom底线
      this.drawLine(this.canvansW / 2, 0, this.canvansW / 2, moveLineH, axisColor, 2) // 中间播放点时间线
      this.add_events()
      var time = start_timestamp + (hours_per_ruler * 3600 * 1000) / 2
      this.ctx.fillStyle = axisColor
      this.ctx.fillText(this.changeTime(time), this.canvansW / 2 - 50, moveTextH)
    },

    /**
     * 绘制添加刻度
     */
    add_graduations(start_timestamp) {
      var px_per_min = this.canvansW / (hours_per_ruler * 60) // px/min
      var px_per_ms = this.canvansW / (hours_per_ruler * 60 * 60 * 1000) // px/ms
      var px_per_step = graduation_step // px/格 默认最小值20px
      var min_per_step = px_per_step / px_per_min // min/格
      for (let i = 0; i < minutes_per_step.length; i++) {
        if (min_per_step <= minutes_per_step[i]) {
          // 让每格时间在minutes_per_step规定的范围内
          min_per_step = minutes_per_step[i]
          px_per_step = px_per_min * min_per_step
          break
        }
      }
      var medium_step = 30
      for (let i = 0; i < minutes_per_step.length; i++) {
        if (distance_between_gtitle / px_per_min <= minutes_per_step[i]) {
          medium_step = minutes_per_step[i]
          break
        }
      }
      var num_steps = this.canvansW / px_per_step // 总格数
      var graduation_left
      var graduation_time
      // eslint-disable-next-line no-unused-vars
      let caret_class
      var lineH // 刻度线高度
      var ms_offset = this.ms_to_next_step(start_timestamp, min_per_step * 60 * 1000) // 开始的偏移时间 ms
      var px_offset = ms_offset * px_per_ms // 开始的偏移距离 px
      var ms_per_step = px_per_step / px_per_ms // ms/step
      for (let i = 0; i < num_steps; i++) {
        graduation_left = px_offset + i * px_per_step // 距离=开始的偏移距离+格数*px/格
        graduation_time = start_timestamp + ms_offset + i * ms_per_step // 时间=左侧开始时间+偏移时间+格数*ms/格
        var date = new Date(graduation_time)
        if (date.getHours() === 0 && date.getMinutes() === 0) {
          caret_class = 'big'
          lineH = 35
          var big_date = '00:00'
          this.ctx.fillStyle = fontColor // 0点  字体样式
          this.ctx.font = font
          this.ctx.fillText(big_date, graduation_left, 50)
        } else if ((graduation_time / (60 * 1000)) % medium_step === 0) {
          caret_class = 'middle'
          lineH = 25
          var middle_date = this.graduation_title(date)
          this.ctx.font = font
          this.ctx.fillText(middle_date, graduation_left - 10, 50)
        } else {
          lineH = 15
        }
        this.ctx.fillStyle = fontColor // 除了0点 以外字体的颜色
        this.drawLine(
          graduation_left,
          0,
          graduation_left,
          lineH,
          scaleLineCorols, // 刻度线颜色
          1
        )
      }
      this.ctx.font = font
    },

    /**
     * 绘制线
     * @param {*} beginX
     * @param {*} beginY
     * @param {*} endX
     * @param {*} endY
     * @param {*} color
     * @param {*} width
     */
    drawLine(beginX, beginY, endX, endY, color, width) {
      this.ctx.beginPath()
      this.ctx.moveTo(beginX, beginY)
      this.ctx.lineTo(endX, endY)
      this.ctx.strokeStyle = color
      this.ctx.lineWidth = width
      this.ctx.stroke()
    },

    /**
     * 添加录像段
     * @param {*} cells 录像数组
     */
    add_cells(cells) {
      cells.forEach((cell) => {
        this.draw_cell(cell)
      })
    },

    /**
     * 绘制录像块
     * @param {*} cell cell包括beginTime ms;endTime ms;style
     */
    draw_cell(cell) {
      var px_per_ms = this.canvansW / (hours_per_ruler * 60 * 60 * 1000) // px/ms
      var beginX = (cell.beginTime - this.start_timestamp) * px_per_ms
      var cell_width = (cell.beginTime - cell.endTime) * px_per_ms
      this.ctx.fillStyle = cell.style.background
      this.ctx.fillRect(beginX, 0, cell_width, scaleH)
    },

    /**
     * 绘制录像块背景
     */
    drawCellBg() {
      // this.ctx.fillStyle = canvasColors[0] // 刻度背景颜色
      this.ctx.fillStyle = rulesContent // 刻度背景颜色
      this.ctx.fillRect(0, 0, this.canvansW, scaleH)
    },

    /**
     * 时间轴事件
     */
    add_events() {
      this.canvas.addEventListener('mousewheel', this.mousewheelFunc) // 鼠标滚动放大缩小
      this.canvas.addEventListener('mousedown', this.mousedownFunc) // 拖动时间轴事件
      this.canvas.addEventListener('mousemove', this.mousemoveFunc) // 鼠标移动事件
      this.canvas.addEventListener('mouseup', this.mouseupFunc) // 鼠标左右键点击移动事件
      this.canvas.addEventListener('mouseout', this.mouseoutFunc) // 鼠标左右键离开事件
    },

    /**
     * 拖动/点击 mousedown事件
     */
    mousedownFunc(e) {
      this.g_isMousedown = true
      g_mousedownCursor = this.get_cursor_x_position(e) // 记住mousedown的位置
      // console.log(g_mousedownCursor)
    },

    /**
     * 拖动/鼠标hover显示 mousemove事件
     */
    mousemoveFunc(e) {
      var pos_x = this.get_cursor_x_position(e)
      // console.log(pos_x)
      var px_per_ms = this.canvansW / (hours_per_ruler * 60 * 60 * 1000) // px/ms
      this.clearCanvas()
      if (this.g_isMousedown) {
        var diff_x = pos_x - g_mousedownCursor
        this.start_timestamp = this.start_timestamp - Math.round(diff_x / px_per_ms)
        this.init(this.start_timestamp, this.timecell)
        this.g_isMousemove = true
        g_mousedownCursor = pos_x
      } else {
        var time = this.start_timestamp + pos_x / px_per_ms
        this.init(this.start_timestamp, this.timecell)
        this.drawLine(pos_x, 0, pos_x, moveLineH + 10, moveLineColor, 1) // 鼠标移动的线
        this.ctx.fillStyle = moveLineColor // 鼠标移动时候的文字
        this.ctx.fillText(this.changeTime(time), pos_x - 50, moveTextH + 10) //  pos_x - 50 鼠标移入时时间的偏移
      }
      this.ctx.font = '12px pf'
    },
    /**
     * 拖动/点击 mouseup事件
     */
    mouseupFunc(e) {
      if (this.g_isMousemove) {
        // 拖动 事件
        this.g_isMousemove = false
        this.g_isMousedown = false
        this.returnTime = this.start_timestamp + (hours_per_ruler * 3600 * 1000) / 2
      } else {
        // click 事件
        this.g_isMousedown = false
        var posx = this.get_cursor_x_position(e) // 鼠标距离 px
        var ms_per_px = (zoom * 3600 * 1000) / this.canvansW // ms/px
        this.returnTime = this.start_timestamp + posx * ms_per_px
        this.set_time_to_middle(this.returnTime)
      }
    },

    /**
     * 鼠标移出隐藏时间 mouseout事件
     * @param {*} e
     */
    mouseoutFunc(e) {
      this.clearCanvas()
      this.init(this.start_timestamp, this.timecell)
    },

    /**
     * 滚轮放大缩小，以时间轴中心为准 mousewheel事件
     */
    mousewheelFunc() {
      if (event && event.preventDefault) {
        event.preventDefault()
      } else {
        window.event.returnValue = false
        return false
      }

      var e = window.event || event
      var delta = Math.max(-1, Math.min(1, e.wheelDelta || -e.detail))
      var middle_time = this.start_timestamp + (hours_per_ruler * 3600 * 1000) / 2 // ms 记住当前中间的时间
      if (delta < 0) {
        zoom = zoom + 4
        if (zoom >= 24) {
          zoom = 24 // 放大最大24小时
        }
        hours_per_ruler = zoom
      } else if (delta > 0) {
        // 放大
        zoom = zoom - 4
        if (zoom <= 1) {
          zoom = 1 // 缩小最小1小时
        }
        hours_per_ruler = zoom
      }

      this.clearCanvas()
      this.start_timestamp = middle_time - (hours_per_ruler * 3600 * 1000) / 2 // start_timestamp = 当前中间的时间 - zoom/2
      this.init(this.start_timestamp, this.timecell)
    },

    /**
     * 获取鼠标posx
     * @param {*} e
     */
    get_cursor_x_position(e) {
      var posx = 0
      if (!e) {
        e = window.event
      }
      // if (e.pageX || e.pageY) { // 鼠标相对于浏览器左上角x轴和Y轴的坐标，随滚动变化而变化
      //   posx = e.pageX
      // } else if (e.clientX || e.clientY) { // 鼠标相对于浏览器左上角x轴和Y轴的坐标，不随滚动变化而变化
      //   posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft
      // }
      if (e.offsetX || e.offsetY) {
        // 鼠标相对于事件源左上角的X轴和Y轴的坐标
        posx = e.offsetX
      }
      return posx
    },

    /**
     * 返回时间轴上刻度的时间
     * @param {*} datetime new Date 格式
     */
    graduation_title(datetime) {
      if (datetime.getHours() === 0 && datetime.getMinutes() === 0 && datetime.getMilliseconds() === 0) {
        //   console.log(datetime.getDate())
        return ('0' + datetime.getDate().toString()).substr(-2) + '.' + ('0' + (datetime.getMonth() + 1).toString()).substr(-2) + '.' + datetime.getFullYear()
      }
      return datetime.getHours() + ':' + ('0' + datetime.getMinutes().toString()).substr(-2)
    },

    /**
     * 返回 2018-01-01 10:00:00 格式时间
     * @param {*} time
     */
    changeTime(time) {
      var newTime = new Date(time)
      var year = newTime.getFullYear()
      var month = newTime.getMonth() + 1
      if (month < 10) {
        month = '0' + month
      }
      var date = newTime.getDate()
      if (date < 10) {
        date = '0' + date
      }
      var hour = newTime.getHours()
      if (hour < 10) {
        hour = '0' + hour
      }
      var minute = newTime.getMinutes()
      if (minute < 10) {
        minute = '0' + minute
      }
      var second = newTime.getSeconds()
      if (second < 10) {
        second = '0' + second
      }
      return year + '-' + month + '-' + date + ' ' + hour + ':' + minute + ':' + second
    },

    /**
     * 左侧开始时间的偏移，返回单位ms
     * @param {*} timestamp
     * @param {*} step
     */
    ms_to_next_step(timestamp, step) {
      var remainder = timestamp % step
      return remainder ? step - remainder : 0
    },

    /**
     * 设置时间，让这个时间点跳到中间红线处
     *  @param {*} time 单位ms
     */
    set_time_to_middle(time) {
      this.clearCanvas()
      this.start_timestamp = time - (hours_per_ruler * 60 * 60 * 1000) / 2
      this.init(this.start_timestamp, this.timecell)
    },

    returnMouseupTime() {
      if (this.returnTime != null) {
        return this.returnTime
      }
    },

    /**
     * 清除canvas 每次重新绘制需要先清除
     */
    clearCanvas() {
      this.ctx.clearRect(0, 0, 1040, 90)
    },

    // 转换时间戳
    getTimestamp(time) {
      // 把时间日期转成时间戳
      return new Date(time).getTime() / 1000
    },
  },
}
</script>
<style lang="scss">
.bigBox {
  width: 100%;
}
</style>
